<?php

namespace App\Traits;

use Illuminate\Http\JsonResponse;
use Symfony\Component\HttpFoundation\Response as FoundationResponse;

trait ApiResponse
{

    /**
     * @var int
     */
    protected int $statusCode = FoundationResponse::HTTP_OK;
    protected int $jsonCode = 200;

    /**
     * @return int
     */
    public function getStatusCode(): int
    {
        return $this->statusCode;
    }

    /**
     * @param int $statusCode
     * @return $this
     */
    public function setStatusCode(int $statusCode): static
    {

        $this->statusCode = $statusCode;
        return $this;
    }

    public function setJsonCode(int $jsonCode): static
    {

        $this->jsonCode = $jsonCode;
        return $this;
    }

    public function getJsonCode(): int
    {

        return $this->jsonCode;
    }

    /**
     * @param $data
     * @param array $header
     * @return JsonResponse
     */
    public function respond($data, array $header = []): JsonResponse
    {

        return response()->json($data, $this->statusCode, $header);
    }

    /**
     * @param string $status
     * @param array $data
     * @param int $code
     * @return JsonResponse
     */
    public function status(string $status, array $data, int $code = 0): JsonResponse
    {

        if ($code) {
            $this->setStatusCode($code);
        }

        $status = [
            'status' => $status,
            'code' => $this->jsonCode
        ];

        $data = array_merge($status, $data);
        return $this->respond($data);
    }

    /**
     * @param string $message
     * @param string $status
     * @return JsonResponse
     */
    public function unauthorized(string $message, int $jsonCode = FoundationResponse::HTTP_UNAUTHORIZED, string $status = 'unauthorized'): JsonResponse
    {
        return $this->setStatusCode(FoundationResponse::HTTP_UNAUTHORIZED)->setJsonCode($jsonCode)->message($message, $status);
    }

    /**
     * 业务错误
     * @param string $message
     * @param int $code
     * @param string $status
     * @return JsonResponse
     */
    public function failed(string $message, int $jsonCode = 400, string $status = 'error'): JsonResponse
    {

        return $this->setStatusCode(FoundationResponse::HTTP_BAD_REQUEST)->setJsonCode($jsonCode)->message($message, $status);
    }

    /**
     * @param string $message
     * @param string $status
     * @return JsonResponse
     */
    public function message(string $message, string $status = "success"): JsonResponse
    {

        return $this->status($status, [
            'message' => $message
        ]);
    }

    /**
     * 程序错误
     * @param string $message
     * @return JsonResponse
     */
    public function error(string $message = "Internal Error!", int $jsonCode = 500, $status = 'server error'): JsonResponse
    {

        return $this->setStatusCode(FoundationResponse::HTTP_INTERNAL_SERVER_ERROR)->setJsonCode($jsonCode)->message($message, $status);
    }

    /**
     * @param string $message
     * @return JsonResponse
     */
    public function created(string $message = "created", $jsonCode = 201): JsonResponse
    {
        return $this->setStatusCode(FoundationResponse::HTTP_CREATED)
            ->setJsonCode($jsonCode)
            ->message($message);
    }

    /**
     * 成功返回
     * @param  $data
     * @param string $status
     * @param int $code
     * @return JsonResponse
     */
    public function success($data, string $status = "success", int $jsonCode = 200): JsonResponse
    {

        if (isset($data['data'])) {
            return $this->setJsonCode($jsonCode)->status($status, $data, FoundationResponse::HTTP_OK);
        } else {
            return $this->setJsonCode($jsonCode)->status($status, compact('data'), FoundationResponse::HTTP_OK);
        }
    }

    /**
     * 查无此数据
     * @param string $message
     * @return JsonResponse
     */
    public function notFound(string $message = 'Not Fond!'): JsonResponse
    {
        return $this->setStatusCode(FoundationResponse::HTTP_BAD_REQUEST)->setJsonCode(FoundationResponse::HTTP_NOT_FOUND)->message($message, 'not Fond!');
    }
}
